package multiplex.dataaccess.dao;

import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import multiplex.dataaccess.DaoException;
import multiplex.model.Localizacao;
import multiplex.model.PromocaoLocalizacao;

public class PromocaoLocalizacaoDao 
		extends AbstractDao implements IPromocaoDao<PromocaoLocalizacao> {
	
	public PromocaoLocalizacao get(int id) throws DaoException {
		try{
			PreparedStatement st = getConnection().prepareStatement("SELECT Promocao.id AS id, " +
					"Promocao.nome AS nome, Promocao.desconto AS desconto, Promocao.descricao AS descricao, " +
					"PromocaoLocalizacao.Localizacao_id AS Localizacao_id, " +
					"PromocaoLocalizacao.dataTermino AS dataTermino FROM " +
					"PromocaoLocalizacao, Promocao WHERE PromocaoLocalizacao.Promocao_id = Promocao.id AND " +
					"Promocao.id = ?");
			st.setInt(1, id);
			ResultSet rs = st.executeQuery();
			if(rs.next()){
				PromocaoLocalizacao promocaoLocalizacao = new PromocaoLocalizacao();
				fillPromocaoLocalizacao(promocaoLocalizacao, rs);
				st.close();
				return promocaoLocalizacao;
			}
		} catch(Exception e){
			throw new DaoException(e);
		}
		return null;
	}

	public List<PromocaoLocalizacao> getAll() throws DaoException {
		List<PromocaoLocalizacao> promocaoLocalizacaoList = new ArrayList<PromocaoLocalizacao>();
		try{
			PreparedStatement st = getConnection().prepareStatement("SELECT Promocao.id AS id, " +
					"Promocao.nome AS nome, Promocao.desconto AS desconto, Promocao.descricao AS descricao, " +
					"PromocaoLocalizacao.Localizacao_id AS Localizacao_id, " +
					"PromocaoLocalizacao.dataTermino AS dataTermino FROM " +
					"PromocaoLocalizacao, Promocao WHERE PromocaoLocalizacao.Promocao_id = Promocao.id");
			ResultSet rs = st.executeQuery();
			while(rs.next()){
				PromocaoLocalizacao promocaoLocalizacao = new PromocaoLocalizacao();
				fillPromocaoLocalizacao(promocaoLocalizacao, rs);
				promocaoLocalizacaoList.add(promocaoLocalizacao);
			}
			st.close();
			return promocaoLocalizacaoList;
		}catch(Exception e){
			throw new DaoException(e);
		}
	}
	
	public List<PromocaoLocalizacao> getAllFromLocalizacao(Localizacao localizacao) throws DaoException {
		List<PromocaoLocalizacao> promocaoLocalizacaoList = new ArrayList<PromocaoLocalizacao>();
		try{
			PreparedStatement st = getConnection().prepareStatement("SELECT Promocao.id AS id, " +
					"Promocao.nome AS nome, Promocao.desconto AS desconto, Promocao.descricao AS descricao, " +
					"PromocaoLocalizacao.Localizacao_id AS Localizacao_id, " +
					"PromocaoLocalizacao.dataTermino AS dataTermino FROM " +
					"PromocaoLocalizacao, Promocao WHERE PromocaoLocalizacao.Promocao_id = Promocao.id AND " +
					"PromocaoLocalizacao.Localizacao_id = ?");
			st.setInt(1, localizacao.getId());
			ResultSet rs = st.executeQuery();
			while(rs.next()){
				PromocaoLocalizacao promocaoLocalizacao = new PromocaoLocalizacao();
				fillPromocaoLocalizacao(promocaoLocalizacao, rs);
				promocaoLocalizacaoList.add(promocaoLocalizacao);
			}
			st.close();
			return promocaoLocalizacaoList;
		}catch(Exception e){
			throw new DaoException(e);
		}
	}

	public void save(PromocaoLocalizacao promocaoLocalizacao) throws DaoException {
		try {
			try{
				getConnection().setAutoCommit(false);
				PreparedStatement stPromocao = getConnection().prepareStatement("INSERT INTO " +
						"Promocao(nome, descricao, desconto) VALUES (?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
				fillPreparatedStatementPromocao(stPromocao, promocaoLocalizacao);
				stPromocao.execute();
				ResultSet rs = stPromocao.getGeneratedKeys();
				rs.next();
				promocaoLocalizacao.setId(rs.getInt(1));
				PreparedStatement stPromocaoLocalizacao = getConnection().prepareStatement(
						"INSERT INTO PromocaoLocalizacao (Promocao_id, Localizacao_id, dataTermino) " +
						"VALUES (?,?,?)");
				fillPreparatedStatementPromocaoLocalizacao(stPromocaoLocalizacao, promocaoLocalizacao);
				stPromocaoLocalizacao.execute();
				getConnection().commit();
				stPromocao.close();
				stPromocaoLocalizacao.close();
			} catch(Throwable e){
				getConnection().rollback();
				throw new DaoException(e);
			} finally {
				getConnection().setAutoCommit(true);
			}
		} catch (Exception e) {
			throw new DaoException(e);
		}
	}
	
	public void update(PromocaoLocalizacao promocaoLocalizacao) throws DaoException {
		try {
			try{
				getConnection().setAutoCommit(false);
				PreparedStatement stPromocao = getConnection().prepareStatement("UPDATE Promocao " +
						"SET nome=?, descricao=?, desconto=? WHERE id=?");
				fillPreparatedStatementPromocao(stPromocao, promocaoLocalizacao);
				stPromocao.setInt(4, promocaoLocalizacao.getId());
				PreparedStatement stPromocaoLocalizacao = getConnection().prepareStatement(
						"UPDATE PromocaoLocalizacao SET Localizacao_id=?, dataTermino=? " +
						"WHERE Promocao_id=?");
				fillPreparatedStatementPromocaoLocalizacao(stPromocaoLocalizacao, promocaoLocalizacao);
				stPromocao.execute();
				stPromocaoLocalizacao.execute();
				getConnection().commit();
				stPromocao.close();
				stPromocaoLocalizacao.close();
			} catch(Throwable e){
				getConnection().rollback();
				throw new DaoException(e);
			} finally {
				getConnection().setAutoCommit(true);
			}
		} catch (Exception e) {
			throw new DaoException(e);
		}
	}

	public void remove(PromocaoLocalizacao promocaoLocalizacao) throws DaoException {
		// PromocaoLocalizacao é apagada com base no CASCADE ALL
		try{
			PreparedStatement st = getConnection().prepareStatement(
					"DELETE FROM Promocao WHERE id=?");
			st.setInt(1, promocaoLocalizacao.getId());
			st.execute();
			st.close();		
		}catch(Throwable e){
			throw new DaoException(e);
		}	
	}
	
	private void fillPromocaoLocalizacao(PromocaoLocalizacao promocaoLocalizacao, ResultSet rs) throws SQLException {
		promocaoLocalizacao.setId(rs.getInt("id"));
		promocaoLocalizacao.setNome(rs.getString("nome"));
		promocaoLocalizacao.setDescricao(rs.getString("descricao"));
		promocaoLocalizacao.setDesconto(rs.getFloat("desconto"));
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(rs.getDate("dataTermino"));
		promocaoLocalizacao.setDataTermino(calendar);
		LocalizacaoDao localizacaoDao = new LocalizacaoDao();
		Localizacao localizacao = localizacaoDao.get(rs.getInt("Localizacao_id"));
		promocaoLocalizacao.setLocalizacao(localizacao);
	}
	
	private void fillPreparatedStatementPromocao(PreparedStatement st, PromocaoLocalizacao promocaoLocalizacao) 
			throws SQLException {
		st.setString(1,promocaoLocalizacao.getNome());
		st.setString(2, promocaoLocalizacao.getDescricao());
		st.setDouble(3,promocaoLocalizacao.getDesconto());
	}
	
	private void fillPreparatedStatementPromocaoLocalizacao(PreparedStatement st, PromocaoLocalizacao promocaoLocalizacao) 
			throws SQLException {
		st.setInt(1,promocaoLocalizacao.getId());
		st.setInt(2, promocaoLocalizacao.getLocalizacao().getId());
		st.setDate(3, new Date(promocaoLocalizacao.getDataTermino().getTimeInMillis()));
	}
	
}
